
package com.jf.cloud.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.jf.cloud.api.payment.vo.ShopAccountDetailVO;
import com.jf.cloud.api.user.dto.FinanceDetailDTO;
import com.jf.cloud.api.order.feign.OrderRefundFeignClient;
import com.jf.cloud.api.order.feign.OrderSettlementFeignClient;
import com.jf.cloud.api.user.vo.FinanceDetailExcelVO;
import com.jf.cloud.api.user.vo.FinanceDetailVO;
import com.jf.cloud.api.order.vo.OrderRefundSimpleVO;
import com.jf.cloud.api.order.vo.OrderSettlementSimpleVO;
import com.jf.cloud.api.user.bo.BalanceRefundBO;
import com.jf.cloud.api.user.vo.UserPayInfoVO;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.constant.PayType;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageAdapter;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.user.constant.RechargeIoTypeEnum;
import com.jf.cloud.user.constant.RechargeTypeEnum;
import com.jf.cloud.user.mapper.UserBalanceLogMapper;
import com.jf.cloud.user.mapper.UserExtensionMapper;
import com.jf.cloud.user.mapper.UserLevelLogMapper;
import com.jf.cloud.user.model.UserBalanceLog;
import com.jf.cloud.user.service.UserBalanceLogService;
import com.jf.cloud.user.vo.UserBalanceLogVO;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 余额记录
 *
 * @author zz
 * @date 2021-04-27 15:51:36
 */
@Service
public class UserBalanceLogServiceImpl implements UserBalanceLogService {

    @Autowired
    private UserBalanceLogMapper userBalanceLogMapper;
    @Autowired
    private UserExtensionMapper userExtensionMapper;
    @Autowired
    private OrderSettlementFeignClient orderSettlementFeignClient;
    @Autowired
    private OrderRefundFeignClient orderRefundFeignClient;
    @Autowired
    private UserLevelLogMapper userLevelLogMapper;
    @Autowired
    private MapperFacade mapperFacade;

    @Override
    public PageVO<UserBalanceLog> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> userBalanceLogMapper.list());
    }

    @Override
    public UserBalanceLog getByBalanceLogId(Long balanceLogId) {
        return userBalanceLogMapper.getByBalanceLogId(balanceLogId);
    }

    @Override
    public void save(UserBalanceLog userBalanceLog) {
        userBalanceLogMapper.save(userBalanceLog);
    }

    @Override
    public void update(UserBalanceLog userBalanceLog) {
        userBalanceLogMapper.update(userBalanceLog);
    }

    @Override
    public void deleteById(Long balanceLogId) {
        userBalanceLogMapper.deleteById(balanceLogId);
    }

    @Override
    public PageVO<UserBalanceLogVO> getPageByUserId(PageDTO pageDTO, Long userId) {
        PageVO<UserBalanceLogVO> pageVO = new PageVO<>();
        List<UserBalanceLogVO> userBalanceLogs = userBalanceLogMapper.listByUserId(new PageAdapter(pageDTO), userId);
        // 通过支付单号或者退款单号查询订单号
        List<Long> refundIds = new ArrayList<>();
        List<Long> payIds = new ArrayList<>();
        userBalanceLogs.forEach(item -> {
            if (Objects.equals(item.getType(), RechargeTypeEnum.PAY.value()) && Objects.nonNull(item.getPayId())) {
                payIds.add(item.getPayId());
            } else if (Objects.equals(item.getType(), RechargeTypeEnum.REFUND.value()) && Objects.nonNull(item.getRefundId())) {
                refundIds.add(item.getRefundId());
            }
        });
        ServerResponseEntity<List<OrderSettlementSimpleVO>> orderSettlementRes = orderSettlementFeignClient.listOrderIdsByPayIds(userId, payIds);
        ServerResponseEntity<List<OrderRefundSimpleVO>> orderRefundRes = orderRefundFeignClient.listOrderIdsByRefundIds(refundIds);
        if (orderRefundRes.isSuccess() && orderRefundRes.isSuccess()) {
            Map<Long, OrderSettlementSimpleVO> orderSettlementSimpleMap = orderSettlementRes.getData().stream().collect(Collectors.toMap(OrderSettlementSimpleVO::getPayId, orderSettlementSimpleVO -> orderSettlementSimpleVO));
            Map<Long, OrderRefundSimpleVO> orderRefundSimpleMap = orderRefundRes.getData().stream().collect(Collectors.toMap(OrderRefundSimpleVO::getRefundId, orderRefundSimpleVO -> orderRefundSimpleVO));
            Map<Long, List<UserBalanceLogVO>> userBalanceLogMap = userBalanceLogs.stream().filter(o -> Objects.nonNull(o.getPayId())).collect(Collectors.groupingBy(UserBalanceLogVO::getPayId));
            userBalanceLogs.forEach(item -> {
                if (Objects.equals(item.getType(), RechargeTypeEnum.PAY.value()) && Objects.nonNull(orderSettlementSimpleMap.get(item.getPayId()))) {
                    OrderSettlementSimpleVO orderSettlementSimpleVO = orderSettlementSimpleMap.get(item.getPayId());
                    item.setOrderIds(orderSettlementSimpleVO.getOrderIds());
                    if (Objects.nonNull(orderSettlementSimpleVO.getPayIds())) {
                        // 预售订单要把定金的订单加上
                        String[] orderPayIds = orderSettlementSimpleVO.getPayIds().split(Constant.COMMA);
                        for (String orderPayId : orderPayIds) {
                            if (Objects.equals(orderPayId, item.getPayId().toString())) {
                                continue;
                            }
                            if (CollUtil.isNotEmpty(userBalanceLogMap.get(Long.valueOf(orderPayId)))) {
                                for (UserBalanceLogVO userBalanceLogVO : userBalanceLogMap.get(Long.valueOf(orderPayId))) {
                                    userBalanceLogVO.setOrderIds(orderSettlementSimpleVO.getOrderIds());
                                }
                            }
                        }
                    }
                }else if (Objects.equals(item.getType(), RechargeTypeEnum.REFUND.value()) && Objects.nonNull(orderRefundSimpleMap.get(item.getRefundId()))) {
                    item.setOrderIds( new ArrayList<Long>(){{ this.add(orderRefundSimpleMap.get(item.getRefundId()).getOrderId()); }} );
                }
            });
        }
        pageVO.setList(userBalanceLogs);
        pageVO.setTotal(userBalanceLogMapper.countByUserId(userId));
        pageVO.setPages(PageUtil.getPages(pageVO.getTotal(), pageDTO.getPageSize()));
        return pageVO;
    }

    @Override
    public void deleteByUserId(Long userId) {
        userBalanceLogMapper.deleteByUserId(userId);
    }

    @Override
    public Long saveBatch(List<UserBalanceLog> userBalanceLogs) {
        return userBalanceLogMapper.saveBatch(userBalanceLogs);
    }




    @Override
    public UserBalanceLog getByPayId(Long payId) {
        return userBalanceLogMapper.getByPayId(payId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateToOrderPaySuccess(Long payId, UserBalanceLog userBalanceLog) {
        // 扣减余额，并将余额记录的支付状态变为已支付
        Long userId = userBalanceLog.getUserId();
        int updateBalanceStatus = userExtensionMapper.deductionUserBalance(userBalanceLog.getChangeBalance(), userId);
        if (updateBalanceStatus < 1) {
            throw new LuckException("余额不足");
        }
        int updateLogStatus = userBalanceLogMapper.updateToSuccess(userBalanceLog.getBalanceLogId(), userBalanceLog.getPayId(), PayType.BALANCE.value());
        if (updateLogStatus < 1) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doRefund(BalanceRefundBO balanceRefundBO) {
        int refundCount = userBalanceLogMapper.countByRefundId(balanceRefundBO.getRefundId(),balanceRefundBO.getRefundNumber());
        if (refundCount > 0) {
            return;
        }
        // 退款记录
        UserBalanceLog userBalanceLog = new UserBalanceLog();
        userBalanceLog.setUserId(balanceRefundBO.getUserId());
        userBalanceLog.setChangeBalance(balanceRefundBO.getChangeBalance());
        userBalanceLog.setIoType(RechargeIoTypeEnum.INCOME.value());
        userBalanceLog.setIsPayed(0);
        userBalanceLog.setPayId(balanceRefundBO.getPayId());
        userBalanceLog.setRefundId(balanceRefundBO.getRefundId());
        userBalanceLog.setRefundNumber(balanceRefundBO.getRefundNumber());
        userBalanceLog.setType(RechargeTypeEnum.REFUND.value());
        userBalanceLogMapper.save(userBalanceLog);

        // 余额加钱
        userExtensionMapper.addByUserBalanceLog(userBalanceLog);
    }

    @Override
    public PageVO<FinanceDetailVO> pageFinanceDetail(PageDTO pageDTO, FinanceDetailDTO financeDetailDTO) {
        return PageUtil.doPage(pageDTO, ()-> userBalanceLogMapper.listFinanceDetail(financeDetailDTO));
    }

    @Override
    public PageVO<FinanceDetailVO> pageFinanceDetailByQrCode(PageDTO pageDTO, FinanceDetailDTO financeDetailDTO) {
        return PageUtil.doPage(pageDTO, ()-> userBalanceLogMapper.listFinanceDetailByQrCode(financeDetailDTO));
    }

    @Override
    public List<FinanceDetailExcelVO> listFinanceDetail(FinanceDetailDTO financeDetailDTO) {
        return mapperFacade.mapAsList(userBalanceLogMapper.listFinanceDetail(financeDetailDTO), FinanceDetailExcelVO.class);
    }

    @Override
    public ShopAccountDetailVO getPlatformAccountDetail(Date startTime, Date endTime) {
        ShopAccountDetailVO levelInfo = userLevelLogMapper.getPlatformAccountDetail(startTime, endTime);
        if (Objects.isNull(levelInfo)) {
            levelInfo = new ShopAccountDetailVO();
        }
        ShopAccountDetailVO balanceInfo = userBalanceLogMapper.getPlatformAccountDetail(startTime, endTime);
        if (Objects.isNull(balanceInfo)) {
            balanceInfo = new ShopAccountDetailVO();
        }
        ShopAccountDetailVO platformInfo = new ShopAccountDetailVO();
        platformInfo.setAlipayAmount(getDefaultValue(levelInfo.getAlipayAmount()) + getDefaultValue(balanceInfo.getAlipayAmount()));
        platformInfo.setWechatAmount(getDefaultValue(levelInfo.getWechatAmount()) + getDefaultValue(balanceInfo.getWechatAmount()));
        platformInfo.setBalanceAmount(getDefaultValue(levelInfo.getBalanceAmount()) + getDefaultValue(balanceInfo.getBalanceAmount()));
        platformInfo.setScoreCount(0L);
        platformInfo.setTotal(platformInfo.getAlipayAmount() + platformInfo.getWechatAmount() + platformInfo.getBalanceAmount());
        platformInfo.setShopId(Constant.PLATFORM_SHOP_ID);
        platformInfo.setShopName(Constant.PLATFORM_SHOP_NAME);
        return platformInfo;
    }

    @Override
    public List<UserPayInfoVO> listPayInfoVO(Date startTime, Date endTime) {
        return userBalanceLogMapper.listPayInfo(startTime, endTime);
    }

    private Long getDefaultValue(Long value) {
        if (Objects.isNull(value)) {
            return 0L;
        }
        return value;
    }
}
